Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates Logto Core’s organization invitation creation and status-update flows to return dedicated, localizable error codes (instead of request.invalid_input with English-only details), and synchronizes the corresponding phrase translations and tests.
Changes:
- Replaced several invitation validation failures with
organization.*error codes in Core. - Updated integration tests to assert the new error codes and added coverage for “status not changeable after accepted”.
- Added the new organization error keys across all locale phrase files and introduced a changeset for
@logto/core.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/core/src/routes/organization-invitation/index.ts | Switches request validation errors to dedicated organization.* codes for the invitation routes. |
| packages/core/src/libraries/organization-invitation.ts | Switches library-thrown validation errors to dedicated organization.* codes (and includes a small formatting change). |
| packages/integration-tests/src/tests/api/organization/organization-invitation.creation.test.ts | Updates expected error codes for invitation creation validation. |
| packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts | Updates expected error codes and adds a test for updating an accepted invitation. |
| packages/phrases/src/locales/en/errors/organization.ts | Adds localized messages for the new invitation-related error keys (English). |
| packages/phrases/src/locales/ar/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Arabic). |
| packages/phrases/src/locales/de/errors/organization.ts | Adds localized messages for the new invitation-related error keys (German). |
| packages/phrases/src/locales/es/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Spanish). |
| packages/phrases/src/locales/fa-ir/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Persian). |
| packages/phrases/src/locales/fr/errors/organization.ts | Adds localized messages for the new invitation-related error keys (French). |
| packages/phrases/src/locales/it/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Italian). |
| packages/phrases/src/locales/ja/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Japanese). |
| packages/phrases/src/locales/ko/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Korean). |
| packages/phrases/src/locales/pl-pl/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Polish). |
| packages/phrases/src/locales/pt-br/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Portuguese - Brazil). |
| packages/phrases/src/locales/pt-pt/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Portuguese - Portugal). |
| packages/phrases/src/locales/ru/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Russian). |
| packages/phrases/src/locales/th/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Thai). |
| packages/phrases/src/locales/tr-tr/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Turkish). |
| packages/phrases/src/locales/zh-cn/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Simplified Chinese). |
| packages/phrases/src/locales/zh-hk/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Chinese - Hong Kong). |
| packages/phrases/src/locales/zh-tw/errors/organization.ts | Adds localized messages for the new invitation-related error keys (Chinese - Taiwan). |
| .changeset/org-invitation-error-i18n.md | Declares a release note/version bump for the change in @logto/core. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.
Suppressed comments (1)
packages/core/src/libraries/organization-invitation.ts:72
- Membership detection for existing users is case-sensitive (
isMember(organizationId, invitee)ultimately doesusers.primaryEmail = email). Since other user/email lookups in core use case-insensitive comparisons (e.g.lower(primaryEmail)=lower(email)inqueries/user.ts), this can let an existing member be invited again by varying email casing, and the neworganization.invitee_already_membererror will not trigger reliably.
if (await this.queries.organizations.relations.users.isMember(organizationId, invitee)) {
throw new RequestError({
status: 422,
code: 'organization.invitee_already_member',
});
b875316 to
57abd46
Compare
COMPARE TO
|
| Name | Diff |
|---|---|
| .changeset/org-invitation-error-i18n.md | 📈 +583 Bytes |
| packages/core/src/libraries/organization-invitation.ts | 📈 +197 Bytes |
| packages/core/src/routes/organization-invitation/index.ts | 📈 +152 Bytes |
| packages/integration-tests/src/tests/api/organization/organization-invitation.creation.test.ts | 📈 +26 Bytes |
| packages/integration-tests/src/tests/api/organization/organization-invitation.status.test.ts | 📈 +889 Bytes |
| packages/phrases/src/locales/ar/errors/organization.ts | 📈 +540 Bytes |
| packages/phrases/src/locales/de/errors/organization.ts | 📈 +482 Bytes |
| packages/phrases/src/locales/en/errors/organization.ts | 📈 +441 Bytes |
| packages/phrases/src/locales/es/errors/organization.ts | 📈 +450 Bytes |
| packages/phrases/src/locales/fa-ir/errors/organization.ts | 📈 +546 Bytes |
| packages/phrases/src/locales/fr/errors/organization.ts | 📈 +469 Bytes |
| packages/phrases/src/locales/it/errors/organization.ts | 📈 +439 Bytes |
| packages/phrases/src/locales/ja/errors/organization.ts | 📈 +549 Bytes |
| packages/phrases/src/locales/ko/errors/organization.ts | 📈 +487 Bytes |
| packages/phrases/src/locales/pl-pl/errors/organization.ts | 📈 +459 Bytes |
| packages/phrases/src/locales/pt-br/errors/organization.ts | 📈 +418 Bytes |
| packages/phrases/src/locales/pt-pt/errors/organization.ts | 📈 +419 Bytes |
| packages/phrases/src/locales/ru/errors/organization.ts | 📈 +672 Bytes |
| packages/phrases/src/locales/th/errors/organization.ts | 📈 +747 Bytes |
| packages/phrases/src/locales/tr-tr/errors/organization.ts | 📈 +434 Bytes |
| packages/phrases/src/locales/zh-cn/errors/organization.ts | 📈 +373 Bytes |
| packages/phrases/src/locales/zh-hk/errors/organization.ts | 📈 +373 Bytes |
| packages/phrases/src/locales/zh-tw/errors/organization.ts | 📈 +382 Bytes |
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 57abd46320
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| status: 422, | ||
| code: 'request.invalid_input', | ||
| details: 'The invitee is already a member of the organization.', | ||
| code: 'organization.invitee_already_member', |
There was a problem hiding this comment.
Preserve the released validation error codes
For existing Management API clients that branch on request.invalid_input for these established 400/422 responses, replacing the code with organization.* removes a previously accepted error semantic and breaks their handling. Unless an explicit product decision approved that compatibility break, retain the legacy code and expose any finer-grained discriminator in a backward-compatible way; the same issue applies to all five replacements in this commit.
AGENTS.md reference: AGENTS.md:L37-L37
Useful? React with 👍 / 👎.
| @@ -0,0 +1,7 @@ | |||
| --- | |||
| '@logto/core': minor | |||
There was a problem hiding this comment.
Version the phrases package with its new error keys
For npm consumers of @logto/phrases, this changeset versions only @logto/core, so changeset version leaves the publishable phrases package at its existing version and the repository's pnpm -r publish invocation has no --force; pnpm publish --help confirms that already-registered package versions are processed only with that flag. Consequently, the new locale resources and exported LogtoErrorCode members will not be published; add an @logto/phrases patch entry to the changeset.
AGENTS.md reference: AGENTS.md:L19-L21
Useful? React with 👍 / 👎.
| new RequestError({ | ||
| code: 'request.invalid_input', | ||
| details: 'The value of `expiresAt` must be in the future.', | ||
| code: 'organization.expires_at_in_future', |
There was a problem hiding this comment.
Document the new invitation error codes in OpenAPI
When Management API consumers consult or generate clients from packages/core/src/routes/organization-invitation/index.openapi.json, they still see only the existing generic response descriptions and cannot discover any of the five newly returned codes. Since this change intentionally makes those codes client-distinguishable API behavior, update the corresponding 400/422 response documentation in the same change.
AGENTS.md reference: AGENTS.md:L39-L39
Useful? React with 👍 / 👎.
| status: 422, | ||
| code: 'request.invalid_input', | ||
| details: 'The invitee is already a member of the organization.', | ||
| code: 'organization.invitee_already_member', |
There was a problem hiding this comment.
These five replacements remove error codes that released endpoints have been returning, so any client branching on request.invalid_input for these 400/422 responses (which is what the integration tests did before this PR) silently stops matching. The changeset describes the new codes but not the removal of the old one. If the error code is not part of the stable contract, state that in the changeset; otherwise this needs an explicit product decision. Same for the other four replacements.
| new RequestError({ | ||
| code: 'request.invalid_input', | ||
| details: 'The value of `expiresAt` must be in the future.', | ||
| code: 'organization.expires_at_in_future', |
There was a problem hiding this comment.
The 400/422 descriptions in index.openapi.json still do not name any of the new codes, so they are not discoverable in the generated API reference (openapi.logto.io). Since the point of this change is that clients can distinguish these failures, document the codes in those response descriptions in the same PR.
Summary
Replaces the generic request.invalid_input + English-only details errors in organization invitation create/status-update flows with five dedicated, localized codes under the organization namespace:
invitee_already_member
expires_at_in_future
invitation_status_not_changeable
accepted_user_id_required
accepted_user_email_mismatch
All 18 locale files are synced with translations. Error response codes are not part of Logto's versioned API contract. The replaced codes were generic request.invalid_input with English-only details.
Testing
Checklist
.changeset